package com.github.linkoog.model_designer.ide.editer.dbtable.tab_editer;

import com.github.linkoog.model_designer.common.TableModelEditor;
import com.github.linkoog.model_designer.ide.editer.common.ColumnVo;
import com.github.linkoog.model_designer.ide.editer.DDLSqlDialog;
import com.github.linkoog.model_designer.ide.editer.common.TableVo;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiManager;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.ui.DocumentAdapter;
import com.intellij.util.ObjectUtils;
import com.intellij.util.ui.ColumnInfo;
import com.intellij.util.ui.JBDimension;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.yaml.YAMLElementGenerator;
import org.jetbrains.yaml.YAMLUtil;
import org.jetbrains.yaml.psi.*;

import javax.swing.*;
import javax.swing.border.LineBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import java.awt.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class DBTableLeftPanel implements Disposable, DumbAware {

    public static final Key<DBTableLeftPanel> LEFT_PANEL_KEY = new Key<>("DBTableTabPanel");

    private final Project project;
    private final VirtualFile virtualFile;
    private final YAMLFile yamlFile;
    private final YAMLElementGenerator yamlElementGenerator;


    private JPanel myMainPanel;
    private JPanel topPanel;
    private JPanel contextPanel;

    private JTextField nameTextField;
    private JTextArea commentTextArea;


    private JPanel columnsPanel;



    private JPanel tablePanel;
    private JButton saveButton;
    private JButton cancelButton;
    private JPanel bottomPanel;
    private JButton showDDLButton;

    private ColumnsTableEditer columnsTableEditer;

    public DBTableLeftPanel(Project project, VirtualFile virtualFile){
        this.project = project;
        this.virtualFile = virtualFile;
        //this.virtualFile.putUserData(LEFT_PANEL_KEY, this);
        this.yamlFile = (YAMLFile)PsiManager.getInstance(project).findFile(virtualFile);
        this.yamlElementGenerator = YAMLElementGenerator.getInstance(project);

        initPanelUI();
        bindPanelUIEvent();
        initYamlTableFileds();
    }

    private void initPanelUI(){
        topPanel.setPreferredSize(new JBDimension(-1, 24, true));

        tablePanel.setBorder(new LineBorder(Color.LIGHT_GRAY));

        columnsTableEditer = new ColumnsTableEditer();
        columnsPanel.add(columnsTableEditer.createComponent(), BorderLayout.CENTER);
    }

    private void bindPanelUIEvent(){
        nameTextField.getDocument().addDocumentListener(new DocumentAdapter() {
            @Override
            protected void textChanged(@NotNull DocumentEvent e) {
                final Document document = e.getDocument();
                try {
                    String text = document.getText(0, document.getLength());
                    setYamlValue("name", text);
                } catch (BadLocationException ex) {
                    ex.printStackTrace();
                }
            }
        });

        commentTextArea.getDocument().addDocumentListener(new DocumentAdapter() {
            @Override
            protected void textChanged(@NotNull DocumentEvent e) {
                final Document document = e.getDocument();
                try {
                    String text = document.getText(0, document.getLength());
                    setYamlValue("comment", text);
                } catch (BadLocationException ex) {
                    ex.printStackTrace();
                }
            }
        });

        columnsTableEditer.modelListener(new TableModelEditor.DataChangedListener<ColumnVo>() {
            @Override
            public void dataChanged(@NotNull ColumnInfo<ColumnVo, ?> columnInfo, int rowIndex) {
                System.out.println("===" + rowIndex);
            }
        });

        showDDLButton.addActionListener(e -> {
            TableVo tableVo = new TableVo();
            //tableVo.setTableKeyValue();
            tableVo.setComment(commentTextArea.getText());
            String name = nameTextField.getText();
            if (StringUtils.isBlank(name)){
                Messages.showErrorDialog(myMainPanel, "表名为空！", "错误");
                return;
            } else {
                tableVo.setName(name);
            }

            List<ColumnVo> items = columnsTableEditer.getModel().getItems();
            if (items.isEmpty()){
                Messages.showErrorDialog(myMainPanel, "列为空！", "错误");
                return;
            } else {
                tableVo.setColumns(items);
            }


            DDLSqlDialog showDDLDialog = new DDLSqlDialog(project, tableVo);
            showDDLDialog.showAndGet();
        });

    }

    private void setYamlValue(String key, String text){
        final YAMLDocument root = yamlFile.getDocuments().get(0);
        assert root != null;

        final Application application = ApplicationManager.getApplication();
        application.invokeLater(() -> {WriteCommandAction.runWriteCommandAction(project, () -> {
            YAMLMapping rootMapping = PsiTreeUtil.findChildOfType(root, YAMLMapping.class);
            if (rootMapping == null){
                return;
            }

            YAMLKeyValue nameKeyValue = yamlElementGenerator.createYamlKeyValue(key, text);
            rootMapping.putKeyValue(nameKeyValue);
        });});
    }

    private void initYamlTableFileds(){
        final YAMLDocument root = yamlFile.getDocuments().get(0);
        assert root != null;

        final Application application = ApplicationManager.getApplication();
        application.invokeLater(() -> {WriteCommandAction.runWriteCommandAction(project, () -> {
            YAMLMapping rootMapping = PsiTreeUtil.findChildOfType(root, YAMLMapping.class);
            if (rootMapping == null) {
                final YAMLFile yamlFile = YAMLElementGenerator.getInstance(project).createDummyYamlWithText("name:\ncomment:\ncolumns:\n");
                final YAMLMapping mapping = (YAMLMapping) yamlFile.getDocuments().get(0).getTopLevelValue();
                assert mapping != null;
                rootMapping = ((YAMLMapping)root.add(mapping));
            }else {
                YAMLKeyValue nameKeyValue = rootMapping.getKeyValueByKey("name");
                if (nameKeyValue == null){
                    nameKeyValue = (YAMLKeyValue)rootMapping.addBefore(yamlElementGenerator.createYamlKeyValue("name", ""), rootMapping.getFirstChild());
                }

                YAMLKeyValue commentKeyValue = rootMapping.getKeyValueByKey("comment");
                if (commentKeyValue == null){
                    PsiElement element = rootMapping.addAfter(yamlElementGenerator.createEol(), nameKeyValue);
                    commentKeyValue = (YAMLKeyValue)rootMapping.addAfter(yamlElementGenerator.createYamlKeyValue("comment", ""), element);
                }

                YAMLKeyValue columnsKeyValue = rootMapping.getKeyValueByKey("columns");
                if (columnsKeyValue == null){
                    PsiElement element = rootMapping.addAfter(yamlElementGenerator.createEol(), commentKeyValue);
                    columnsKeyValue = (YAMLKeyValue)rootMapping.addAfter(yamlElementGenerator.createYamlKeyValue("columns", ""), element);
                }
            }
        });});
    }

    //初始化面板内容
    public void resetPanelContext() {
        final YAMLDocument root = yamlFile.getDocuments().get(0);
        assert root != null;
        YAMLMapping rootMapping = PsiTreeUtil.findChildOfType(root, YAMLMapping.class);
        if (rootMapping == null) {
            initYamlTableFileds();
            rootMapping = PsiTreeUtil.findChildOfType(root, YAMLMapping.class);
        }

        assert rootMapping != null;
        YAMLKeyValue nameKeyValue = rootMapping.getKeyValueByKey("name");
        if (nameKeyValue != null){
            String name = nameKeyValue.getValueText();
            nameTextField.setText(StringUtils.isNotBlank(name)? name : "");
        }

        YAMLKeyValue commentKeyValue = rootMapping.getKeyValueByKey("comment");
        if (commentKeyValue != null){
            String comment = commentKeyValue.getValueText();
            commentTextArea.setText(StringUtils.isNotBlank(comment)? comment : "");
        }

        List<ColumnVo> columns = new ArrayList<>();
        YAMLKeyValue columnsKeyValue = rootMapping.getKeyValueByKey("columns");
        YAMLMapping columnsValueMapping = ObjectUtils.tryCast(columnsKeyValue.getValue(), YAMLMapping.class);;
        if (columnsValueMapping != null){
            Collection<YAMLKeyValue> columnsCollection = columnsValueMapping.getKeyValues();
            for (YAMLKeyValue columnKeyValue : columnsCollection) {
                ColumnVo columnVo = ColumnVo.newStringColumnVo();
                columnVo.setName(columnKeyValue.getKeyText());
                columns.add(columnVo);

                YAMLMapping columnMapping = ObjectUtils.tryCast(columnKeyValue.getValue(), YAMLMapping.class);
                String indent = StringUtil.repeatSymbol(' ', YAMLUtil.getIndentInThisLine(columnKeyValue) + 2);
                if (columnMapping == null){
                    //未设置表列的属性
                    StringBuilder builder = new StringBuilder();
                    builder.append(columnKeyValue.getKeyText()).append(":");
                    ColumnVo.defaultAttributeMap.forEach((key, val) -> {
                        builder.append("\n").append(indent).append(key).append(":").append(" ").append(val);
                    });

                    final YAMLFile fileWithKey = YAMLElementGenerator.getInstance(project).createDummyYamlWithText(builder.toString());
                    final YAMLMapping dummyMapping = PsiTreeUtil.findChildOfType(fileWithKey.getDocuments().get(0), YAMLMapping.class);
                    assert dummyMapping != null && dummyMapping.getKeyValues().size() == 1;
                    final YAMLKeyValue dummyKeyValue = dummyMapping.getKeyValues().iterator().next();
                    WriteCommandAction.runWriteCommandAction(project, () -> {
                        columnsValueMapping.putKeyValue(dummyKeyValue);
                    });
                    continue;
                }

                //
                ColumnVo.defaultAttributeMap.forEach((key, val) -> {
                    YAMLKeyValue attrKeyValue = columnMapping.getKeyValueByKey(key);
                    if (attrKeyValue == null){
                        WriteCommandAction.runWriteCommandAction(project, () -> {
                            columnMapping.putKeyValue(yamlElementGenerator.createYamlKeyValue(key, val));
                        });
                    } else {
                        columnVo.setField(key, attrKeyValue.getValueText());
                    }
                });
            }
            columnsTableEditer.reset(columns);
        }
    }


    public void deselectNotify() {
    }

    @Override
    public void dispose() {

    }

    public JPanel getMyMainPanel() {
        return myMainPanel;
    }



}
